﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Input.Touch;
using System.Threading;
using System.Xml.Linq;
using System.IO.IsolatedStorage;
using System.IO;


namespace GameForKids
{

    public class GamePlayPuzzle : DrawableGameComponent
    {
        // bien dem thoi gian
        public float milisecon = 0;
        // hien thi thoi gian choi
        public string timePlay="";
        // cac manh ghep hinh
        List<Tile> listTitle;
        // vi tri mac dinh ban dau cua cac title
        List<Vector2> PositonTemp;
        Vector2 PositonReset;
        // ID manh ghep dan chon
        int ItemChoosed = -1;
        // ngon tay dan giu hinh
        bool isPress = false;
        // vector di chuyen cua manh ghep
        Vector2 moveWay;
        SpriteFont helpfont;
        // so luong hinh da choi o tung level
        public int currentImg = 0;
        Texture2D fullImg;
        List<int> listImg;
        SampleImg reviewImg;
        // kiem tra cho phep play audio
        private SoundEffect correct;
        bool playOneTime = false;
        //kiem tra win
        public bool isWin = false;
        //khai bao mang cac vector ve grid
        public int moved = 0;

        public struct myvector
        {
            public Vector2 v1;
            public Vector2 v2;
            public myvector(Vector2 a, Vector2 b)
            {
                v1 = a;
                v2 = b;
            }
        }
        List<myvector> axisX;
        List<myvector> axisY;
        int row;
        int column;
        int titleWidth;
        int titleHeight;
        // trang thai cua game
        public enum GameStateMini
        {
            playing,
            viewsample,
            win,
        }
        public static GameStateMini gamestatemini;
        // tao co so du lieu
        private string strConnectionString = @"isostore:/PuzzleDB.sdf";
        // khai bao 1 line dung chung khi ve
        Line l;

        public bool configuration = false;

        public static string CongThucGoc = "20*L+20-T";
        public static string CongThucHienTai = "";

        public GamePlayPuzzle(Game game): base(game)
        {
            // khoi tao grid mac dinh
            axisX = new List<myvector>();
            axisY = new List<myvector>();
            row = 2;
            column = 2;
            titleWidth = 275 / column;
            titleHeight = 275 / row;
            for (int i = 0; i <= row; i++)
            {
                Vector2 x1 = new Vector2(100, 50 + (titleHeight * i));
                Vector2 x2 = new Vector2(375, 50 + (titleHeight * i));
                myvector v = new myvector(x1, x2);
                axisY.Add(v);
                x1 = new Vector2(425, 50 + (titleHeight * i));
                x2 = new Vector2(700, 50 + (titleHeight * i));
                v = new myvector(x1, x2);
                axisY.Add(v);
            }
            for (int i = 0; i <= column; i++)
            {
                Vector2 y1 = new Vector2(100 + (titleWidth * i), 50);
                Vector2 y2 = new Vector2(100 + (titleWidth * i), 325);
                myvector v = new myvector(y1, y2);
                axisY.Add(v);
                y1 = new Vector2(425 + (titleWidth * i), 50);
                y2 = new Vector2(425 + (titleWidth * i), 325);
                v = new myvector(y1, y2);
                axisY.Add(v);
            }
            listTitle = new List<Tile>();
            PositonTemp = new List<Vector2>();
            listImg = new List<int> {1,2,3,4,5,6,7,8,9,10};
            helpfont = this.Game.Content.Load<SpriteFont>("Fonts/HelpFont");
            gamestatemini = GameStateMini.playing;
            // tao csdl
            using (ReadAndWrite readAndWriteDB = new ReadAndWrite(strConnectionString))
            {
                if (readAndWriteDB.DatabaseExists() == false)
                {
                    readAndWriteDB.CreateDatabase();
                }
            }
            correct = this.Game.Content.Load<SoundEffect>("Sounds/GamesCorrect");

            Initialize();
            l = new Line(GraphicsDevice, Color.White);
            l.setThickness(2);

            // lay cong thuc
            using (IsolatedStorageFile isolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (isolatedStorageFile.FileExists("CongThuc" + GameForKids.gameState.ToString() + ".txt"))
                {
                    using (IsolatedStorageFileStream isfs = isolatedStorageFile.OpenFile("CongThuc" + GameForKids.gameState.ToString() + ".txt", FileMode.Open))
                    {
                        using (StreamReader reader = new StreamReader(isfs))
                        {
                            while (!reader.EndOfStream)
                            {
                                CongThucHienTai = reader.ReadLine();
                            }
                        }
                    }
                }
            }
            if (CongThucHienTai == "" || CongThucHienTai == null)
                CongThucHienTai = CongThucGoc;

        }


        // luu theo dang ID - ten  - level - diem - ngay
        public void saveScore(int _score)
        {
            using (ReadAndWrite readAndWriteDB = new ReadAndWrite(strConnectionString))
            {
                DataScore newscore = new DataScore
                {
                    ID = DateTime.Now.ToString(),
                    name = GameForKids.userName,
                    level = PuzzleGame.level,
                    score = _score,
                    day = DateTime.Today.ToShortDateString()
                };
                readAndWriteDB.TableScore.InsertOnSubmit(newscore);
                readAndWriteDB.SubmitChanges();
            }
        }
        private IList<DataScore> getListDataScore(string _name, int _level)
        {
            IList<DataScore> listDataScore = null;
            using (ReadAndWrite readAndWrite = new ReadAndWrite(strConnectionString))
            {
                IQueryable<DataScore> dataScoreQuery = from data in readAndWrite.TableScore where data.name.Equals(_name) && data.level == _level select data;
                listDataScore = dataScoreQuery.ToList();
            }
            return listDataScore;
        }
        // cat hinh thanh cac manh
        private void LoadTilesToTheirInitialLocation()
        {
            for (int c = 0; c < column; c++)
                for (int r = 0; r < row; r++)
                {
                    Tile t = new Tile();
                    Vector2 v = new Vector2();
                    t.TextureLocationInSpriteSheet.X = titleWidth * c;
                    t.TextureLocationInSpriteSheet.Y = titleHeight * r;
                    t.Position.X = c * titleWidth + 100;
                    t.Position.Y = r * titleHeight + 52;
                    v.X = c * titleWidth + 100;
                    v.Y = r * titleHeight + 52;
                    t.Location.X = c;
                    t.Location.Y = r;
                    listTitle.Add(t);
                    PositonTemp.Add(v);
                }
        }
        // xao tron vi tri cac manh
        private void LoadTilesIntoRandomLocations()
        {
            int temp;
            Random rand = new Random();
            while (PositonTemp.Count >0)
            {
                temp = rand.Next(0, PositonTemp.Count);
                listTitle[PositonTemp.Count -1 ].Position = PositonTemp[temp];
                PositonTemp.RemoveAt(temp);
            }
        }
        //ve cac o hinh ra
        private void DrawTiles(SpriteBatch spriteBatch)
        {
            foreach(Tile t in listTitle)
                spriteBatch.Draw(fullImg,t.Position,new Rectangle((int)t.TextureLocationInSpriteSheet.X ,(int) t.TextureLocationInSpriteSheet.Y, titleWidth -2, titleHeight -2),
                     Color.White, 0f, Vector2.Zero, 1, SpriteEffects.None, 0);
        }

        public void resetListImg()
        {
            listImg.Clear();
            listImg = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 };
        }

        public void startNewLevel(int _level)
        {
            ChartScreen.listDataScore = this.getListDataScore(GameForKids.userName, PuzzleGame.level);
            ChartScreen.levelOfGame = _level;
            axisX.Clear();
            axisY.Clear();
            listTitle.Clear();
            PositonTemp.Clear();
            isWin = false;
            gamestatemini = GameStateMini.playing;
            playOneTime = true;
            int temp;
            if (currentImg == 5)
            {
                moved = 0;
                milisecon = 0;
                currentImg = 1;
                resetListImg();
                Random rand = new Random();
                temp = rand.Next(0, listImg.Count);
                fullImg = this.Game.Content.Load<Texture2D>("PuzzleGame/pic" + listImg[temp].ToString());
                reviewImg = new SampleImg(this.Game, this.Game.Content.Load<Texture2D>("PuzzleGame/pic" + listImg[temp].ToString()));
                listImg.RemoveAt(temp);
            }
            else
            {
                currentImg++;
                Random rand = new Random();
                temp = rand.Next(0, listImg.Count);
                fullImg = this.Game.Content.Load<Texture2D>("PuzzleGame/pic" + listImg[temp].ToString());
                reviewImg = new SampleImg(this.Game, this.Game.Content.Load<Texture2D>("PuzzleGame/pic" + listImg[temp].ToString()));
                listImg.RemoveAt(temp);
            }

            switch (_level)
            {
                case 1:
                    {
                        row = 2;
                        column = 2;
                        titleWidth = 275 / column;
                        titleHeight = 275 / row;
                        for (int i = 0; i <= row; i++)
                        {
                            Vector2 x1 = new Vector2(100, 50+(titleHeight*i));
                            Vector2 x2 = new Vector2(375, 50 + (titleHeight * i));
                            myvector v = new myvector(x1, x2);
                            axisY.Add(v);
                            x1 = new Vector2(425, 50 + (titleHeight * i));
                            x2 = new Vector2(700, 50 + (titleHeight * i));
                            v = new myvector(x1, x2);
                            axisY.Add(v);
                        }
                        for (int i = 0; i <= column; i++)
                        {
                            Vector2 y1 = new Vector2(100 + (titleWidth * i), 50);
                            Vector2 y2 = new Vector2(100 + (titleWidth * i), 325);
                            myvector v = new myvector(y1, y2);
                            axisY.Add(v);
                            y1 = new Vector2(425 + (titleWidth * i), 50);
                            y2 = new Vector2(425 + (titleWidth * i), 325);
                            v = new myvector(y1, y2);
                            axisY.Add(v);
                        }
                        LoadTilesToTheirInitialLocation();
                        LoadTilesIntoRandomLocations();
                    }
                    break;
                case 2:
                    {
                        row = 2;
                        column = 3;
                        titleWidth = 275 / column;
                        titleHeight = 275 / row;
                        for (int i = 0; i <= row; i++)
                        {
                            Vector2 x1 = new Vector2(100, 50 + (titleHeight * i));
                            Vector2 x2 = new Vector2(375, 50 + (titleHeight * i));
                            myvector v = new myvector(x1, x2);
                            axisY.Add(v);
                            x1 = new Vector2(425, 50 + (titleHeight * i));
                            x2 = new Vector2(700, 50 + (titleHeight * i));
                            v = new myvector(x1, x2);
                            axisY.Add(v);
                        }
                        for (int i = 0; i <= column; i++)
                        {
                            Vector2 y1 = new Vector2(100 + (titleWidth * i), 50);
                            Vector2 y2 = new Vector2(100 + (titleWidth * i), 325);
                            myvector v = new myvector(y1, y2);
                            axisY.Add(v);
                            y1 = new Vector2(425 + (titleWidth * i), 50);
                            y2 = new Vector2(425 + (titleWidth * i), 325);
                            v = new myvector(y1, y2);
                            axisY.Add(v);
                        }
                        LoadTilesToTheirInitialLocation();
                        LoadTilesIntoRandomLocations();
                    }
                    break;
                case 3:
                    {
                        row = 3;
                        column =3;
                        titleWidth = 275 / column;
                        titleHeight = 275 / row;
                        for (int i = 0; i <= row; i++)
                        {
                            Vector2 x1 = new Vector2(100, 50 + (titleHeight * i));
                            Vector2 x2 = new Vector2(375, 50 + (titleHeight * i));
                            myvector v = new myvector(x1, x2);
                            axisY.Add(v);
                            x1 = new Vector2(425, 50 + (titleHeight * i));
                            x2 = new Vector2(700, 50 + (titleHeight * i));
                            v = new myvector(x1, x2);
                            axisY.Add(v);
                        }
                        for (int i = 0; i <= column; i++)
                        {
                            Vector2 y1 = new Vector2(100 + (titleWidth * i), 50);
                            Vector2 y2 = new Vector2(100 + (titleWidth * i), 325);
                            myvector v = new myvector(y1, y2);
                            axisY.Add(v);
                            y1 = new Vector2(425 + (titleWidth * i), 50);
                            y2 = new Vector2(425 + (titleWidth * i), 325);
                            v = new myvector(y1, y2);
                            axisY.Add(v);
                        }
                        LoadTilesToTheirInitialLocation();
                        LoadTilesIntoRandomLocations();
                    }
                    break;
                case 4:
                    {
                        row = 3;
                        column =4;
                        titleWidth = 275 / column;
                        titleHeight = 275 / row;
                        for (int i = 0; i <= row; i++)
                        {
                            Vector2 x1 = new Vector2(100, 50 + (titleHeight * i));
                            Vector2 x2 = new Vector2(375, 50 + (titleHeight * i));
                            myvector v = new myvector(x1, x2);
                            axisY.Add(v);
                            x1 = new Vector2(425, 50 + (titleHeight * i));
                            x2 = new Vector2(700, 50 + (titleHeight * i));
                            v = new myvector(x1, x2);
                            axisY.Add(v);
                        }
                        for (int i = 0; i <= column; i++)
                        {
                            Vector2 y1 = new Vector2(100 + (titleWidth * i), 50);
                            Vector2 y2 = new Vector2(100 + (titleWidth * i), 325);
                            myvector v = new myvector(y1, y2);
                            axisY.Add(v);
                            y1 = new Vector2(425 + (titleWidth * i), 50);
                            y2 = new Vector2(425 + (titleWidth * i), 325);
                            v = new myvector(y1, y2);
                            axisY.Add(v);
                        }
                        LoadTilesToTheirInitialLocation();
                        LoadTilesIntoRandomLocations();
                    }
                    break;
                case 5:
                    {
                        row = 4;
                        column = 4;
                        titleWidth = 275 / column;
                        titleHeight = 275 / row;
                        for (int i = 0; i <= row; i++)
                        {
                            Vector2 x1 = new Vector2(100, 50 + (titleHeight * i));
                            Vector2 x2 = new Vector2(375, 50 + (titleHeight * i));
                            myvector v = new myvector(x1, x2);
                            axisY.Add(v);
                            x1 = new Vector2(425, 50 + (titleHeight * i));
                            x2 = new Vector2(700, 50 + (titleHeight * i));
                            v = new myvector(x1, x2);
                            axisY.Add(v);
                        }
                        for (int i = 0; i <= column; i++)
                        {
                            Vector2 y1 = new Vector2(100 + (titleWidth * i), 50);
                            Vector2 y2 = new Vector2(100 + (titleWidth * i), 325);
                            myvector v = new myvector(y1, y2);
                            axisY.Add(v);
                            y1 = new Vector2(425 + (titleWidth * i), 50);
                            y2 = new Vector2(425 + (titleWidth * i), 325);
                            v = new myvector(y1, y2);
                            axisY.Add(v);
                        }
                        LoadTilesToTheirInitialLocation();
                        LoadTilesIntoRandomLocations();
                    }
                    break;
            }
        }

        //tinh diem
        public int getScore()
        {
            int mark = 0;
            XuLyCongThuc xulycongthuc;
            string s = "";

            xulycongthuc = new XuLyCongThuc();
            s = xulycongthuc.TinhDiem(CongThucHienTai, moved, (int)(milisecon / 1000), PuzzleGame.level);
            double d = double.Parse(s);
            mark = (int)d;

            if (mark >= 10)
                return 10;
            if (mark <= 0)
                mark = 0;
            return mark;
        }
        //kiem tra win
        public bool checkWin()
        {
            for (int i = 0; i < listTitle.Count; i++)
            {
                if(listTitle[i].Position.X != listTitle[i].Location.X*titleWidth+426)
                return false;
            }
            return true;
        }

        public override void Initialize()
        {
            base.Initialize();
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        float timeDelay = 0f;
        public void returnResual(float elapsed)
        {
            timeDelay += elapsed;
            configuration = true;
            if (timeDelay >= 500)
            {
                configuration = false;
                timeDelay = 0;
                isWin = true;
            }
        }

        public void nextPicture(float elapsed)
        {
            timeDelay += elapsed;
            if (timeDelay >= 500)
            {
                timeDelay = 0;
                startNewLevel(PuzzleGame.level);
            }
        }

        public override void Update(GameTime gameTime)
        {
            float elapsed = (float)gameTime.ElapsedGameTime.Milliseconds;
            if (PuzzleGame.viewState == PuzzleGame.ViewState.Playing && gamestatemini == GameStateMini.playing)
            {
                milisecon += elapsed;
                setTimePlay();
            }
            if (checkWin() && !isPress)
            {
                if (GameForKids.ISMUSIC && playOneTime)
                {
                    correct.Play();
                    playOneTime = false;
                }
                if (currentImg < 5)
                {
                    gamestatemini = GameStateMini.win;
                    nextPicture(elapsed);
                }
                else
                {
                    gamestatemini = GameStateMini.win;
                    returnResual(elapsed);
                }
            }
            base.Update(gameTime);
        }

        public void setTimePlay()
        {
            timePlay = ((int)milisecon / 60000).ToString()+" : "+(((int)milisecon/1000)%60).ToString();
        }

        public virtual void Draw(GameTime gametime, SpriteBatch spriteBatch)
        {
            if (!reviewImg.show)
            {
                for (int i = 0; i < axisX.Count; i++)
                {
                    l.DrawLine(spriteBatch, axisX[i].v1, axisX[i].v2);
                }
                for (int i = 0; i < axisY.Count; i++)
                {
                    l.DrawLine(spriteBatch, axisY[i].v1, axisY[i].v2);
                }
                DrawTiles(spriteBatch);
            }
            reviewImg.Draw(spriteBatch);
            spriteBatch.DrawString(helpfont, timePlay, new Vector2(10, 250), Color.White);
            spriteBatch.DrawString(helpfont, moved.ToString(), new Vector2(740, 250), Color.White);
        
        }

        public void TouchEvent(TouchLocation touch)
        {
            if (gamestatemini == GameStateMini.playing)
            {
                reviewImg.TouchEvent(touch);
                switch (touch.State)
                {
                    case TouchLocationState.Pressed:
                        Pressed(touch);
                        break;
                    case TouchLocationState.Moved:
                        Moved(touch);
                        break;
                    case TouchLocationState.Released:
                        Released(touch);
                        break;
                }
            }
        }
        public void Pressed(TouchLocation touch)
        {
            for(int i = 0;i<listTitle.Count;i++)
            {
                if (touch.Position.X > listTitle[i].Position.X && touch.Position.X < listTitle[i].Position.X + titleWidth
                    && touch.Position.Y > listTitle[i].Position.Y && touch.Position.Y < listTitle[i].Position.Y + titleHeight)
                {
                    ItemChoosed = i;
                    isPress = true;
                    moveWay = touch.Position - listTitle[i].Position;
                    PositonReset = listTitle[i].Position;
                }
            }
        }
        public void Moved(TouchLocation touch)
        {
            if (isPress && ItemChoosed > -1)
            {
                listTitle[ItemChoosed].Position = touch.Position - moveWay;
            }
        }
        public void Released(TouchLocation touch)
        {
            if (ItemChoosed > -1)
            {
                if (listTitle[ItemChoosed].Position.X > (listTitle[ItemChoosed].Location.X * titleWidth) + (425 - titleWidth/3)
                    && listTitle[ItemChoosed].Position.X < (listTitle[ItemChoosed].Location.X * titleWidth) + (425 + titleWidth/3)
                    && listTitle[ItemChoosed].Position.Y > (listTitle[ItemChoosed].Location.Y * titleHeight) + (50 - titleHeight/3)
                    && listTitle[ItemChoosed].Position.Y < (listTitle[ItemChoosed].Location.Y * titleHeight) + (50+titleHeight/3))
                {
                    listTitle[ItemChoosed].Position = new Vector2(listTitle[ItemChoosed].Location.X * titleWidth + 426, 
                        listTitle[ItemChoosed].Location.Y * titleHeight + 52);
                    moved++;
                }
                else
                {
                    listTitle[ItemChoosed].Position = PositonReset;
                    moved++;
                }
            }
            isPress = false;
            ItemChoosed = -1;
        }
    }
}
